package cn.frank.framework.king.rest;

/**
 * @description: TODO
 * @author: renjiangyang
 * @date 2025/10/28 16:51:15
 * @since 1.8
 */

import cn.frank.framework.king.domain.vo.Result;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @description: 内存高占用模拟
 */
@Api(tags = "内存模拟开关")
@RestController
@Slf4j
@RequestMapping("/api/mem")
public class MemoryStressController {

    private final AtomicBoolean running = new AtomicBoolean(false);
    private final List<byte[]> memoryBlocks = new ArrayList<>();

    /**
     * 开启内存高占用
     *
     * @param duration 持续时间（秒）
     * @param sizeMb   每秒分配内存大小（MB）
     */
    @ApiOperation(value = "开启内存高占用")
    @ApiOperationSupport(order = 1)
    @GetMapping("/start")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "duration", value = "持续时间(秒)", dataType = "Integer", defaultValue = "10", required = true),
            @ApiImplicitParam(name = "sizeMb", value = "每秒分配内存大小(MB)", dataType = "Integer", defaultValue = "50", required = true)
    })
    public Result<String> startMemory(int duration, int sizeMb) {
        // 如果已有模拟在运行，则先停止原来的
        if (running.get()) {
            running.set(false);
            memoryBlocks.clear();
            log.info("内存高占用模拟已被新任务覆盖，停止旧的模拟");
        }

        running.set(true);
        memoryBlocks.clear();

        Thread t = new Thread(() -> {
            long endTime = System.currentTimeMillis() + duration * 1000L;
            try {
                while (running.get() && System.currentTimeMillis() < endTime) {
                    memoryBlocks.add(new byte[sizeMb * 1024 * 1024]);
                    Thread.sleep(1000); // 每秒分配一次
                }
            } catch (OutOfMemoryError e) {
                log.error("内存分配失败", e);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                running.set(false);
            }
        }, "Memory-Stress-Thread");

        t.setDaemon(true);
        t.start();

        log.info("内存高占用模拟开始，持续 {} 秒，每秒分配 {} MB", duration, sizeMb);
        return Result.success("内存高占用模拟已启动（覆盖旧任务），持续 " + duration + " 秒，每秒分配 " + sizeMb + " MB");
    }


    /**
     * 停止内存模拟
     */
    @ApiOperation(value = "停止内存高占用")
    @ApiOperationSupport(order = 2)
    @GetMapping("/stop")
    public Result<String> stopMemory() {
        if (!running.get()) {
            return Result.fail("内存模拟未运行");
        }
        running.set(false);
        memoryBlocks.clear();
        log.info("内存高占用模拟已停止");
        return Result.success("内存高占用模拟已停止");
    }

    /**
     * 查询内存模拟状态
     */
    @ApiOperation(value = "查询内存模拟状态")
    @ApiOperationSupport(order = 3)
    @GetMapping("/status")
    public Result<String> memoryStatus() {
        return Result.success(running.get() ? "内存模拟正在运行" : "内存模拟已停止");
    }
}